package top.italks.demo.pay.product.controller;

import top.italks.demo.pay.common.api.PayService;
import top.italks.demo.pay.common.bean.MethodType;
import top.italks.demo.pay.common.http.HttpConfigStorage;
import top.italks.demo.pay.platform.wx.WXPayConfig;
import top.italks.demo.pay.platform.wx.api.WxPayConfigStorage;
import top.italks.demo.pay.platform.wx.api.WxPayService;
import top.italks.demo.pay.platform.wx.bean.WxBank;
import top.italks.demo.pay.platform.wx.bean.WxTransactionType;
import top.italks.demo.pay.platform.wx.bean.WxTransferType;
import top.italks.demo.pay.request.QueryOrder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 发起支付入口
 *
 * @author: egan
 * @email test@gmail.com
 * @date 2016/11/18 0:25
 */
@RestController
@RequestMapping("/wxtest")
public class WxPayTestController {

    private PayService service = null;
    private PayService appService = null;
    private PayService appletService = null;

    @Resource
    private WXPayConfig wxPayConfig;

    @PostConstruct
    public void init() {
        wxPayConfig.setAppId("wx1fb0bf4d8c053655");
//        wxPayConfig.setKeyPrivate ("577e97af0b4df6c9b92468197c952199");
        service = new WxPayService(new WxPayConfigStorage(wxPayConfig));

        HttpConfigStorage httpConfigStorage = new HttpConfigStorage();

        //最大连接数
        httpConfigStorage.setMaxTotal(20);
        //默认的每个路由的最大连接数
        httpConfigStorage.setDefaultMaxPerRoute(10);
        service.setRequestTemplateConfigStorage(httpConfigStorage);
    }

    @PostConstruct
    public void initApp() {
        wxPayConfig.setAppId("wx1fb0bf4d8c053655");
//        wxPayConfig.setKeyPrivate ("577e97af0b4df6c9b92468197c952199");
        appService = new WxPayService(new WxPayConfigStorage(wxPayConfig));

        HttpConfigStorage httpConfigStorage = new HttpConfigStorage();

        //最大连接数
        httpConfigStorage.setMaxTotal(20);
        //默认的每个路由的最大连接数
        httpConfigStorage.setDefaultMaxPerRoute(10);
        service.setRequestTemplateConfigStorage(httpConfigStorage);
    }

    @PostConstruct
    public void initApplet() {
        wxPayConfig.setAppId("wx81f1f175ef601eaa");
        appletService = new WxPayService(new WxPayConfigStorage(wxPayConfig));

        HttpConfigStorage httpConfigStorage = new HttpConfigStorage();

        //最大连接数
        httpConfigStorage.setMaxTotal(20);
        //默认的每个路由的最大连接数
        httpConfigStorage.setDefaultMaxPerRoute(10);
        service.setRequestTemplateConfigStorage(httpConfigStorage);
    }

    /**
     * 跳到支付页面
     * 针对实时支付
     * H5支付
     *
     * @param price 金额
     * @return 跳到支付页面
     */
    @RequestMapping(value = "toPay.html", produces = "text/html;charset=UTF-8")
    public String toPay(HttpServletRequest request, BigDecimal price) {
        top.italks.demo.pay.common.bean.PayOrder order = new top.italks.demo.pay.common.bean.PayOrder
                ("订单title",
                        "摘要",
                        null == price ? new BigDecimal(0.01) : price,
                        UUID.randomUUID().toString().replace("-", ""),
                        WxTransactionType.MWEB);
        order.setSpbillCreateIp(request.getHeader("X-Real-IP"));
        StringBuffer requestURL = request.getRequestURL();
        //设置网页地址
        order.setWapUrl(requestURL.substring(0, requestURL.indexOf("/") > 0 ? requestURL.indexOf("/") : requestURL.length()));
        //设置网页名称
        order.setWapName("在线充值");

        Map orderInfo = service.orderInfo(order);
        return service.buildRequest(orderInfo, MethodType.POST);
    }

    /**
     * 公众号支付
     *
     * @param openid openid
     * @param price  金额
     * @return 返回jsapi所需参数
     */
    @RequestMapping(value = "jsapi")
    public Map toPay(String openid, BigDecimal price) {

        top.italks.demo.pay.common.bean.PayOrder order = new top.italks.demo.pay.common.bean.PayOrder("订单title", "摘要",
                null == price ? new BigDecimal(0.01) : price,
                UUID.randomUUID().toString().replace("-", ""),
                WxTransactionType.JSAPI);
        order.setOpenid(openid);

        Map orderInfo = appletService.orderInfo(order);
        orderInfo.put("code", 0);

        return orderInfo;
    }


    /**
     * 获取支付预订单信息
     *
     * @return 支付预订单信息
     */
    @RequestMapping("app")
    public Map<String, Object> app() {
        Map<String, Object> data = new HashMap<>();
        data.put("code", 0);
        top.italks.demo.pay.common.bean.PayOrder order = new top.italks.demo.pay.common.bean.PayOrder("订单title",
                "摘要",
                new BigDecimal(0.01),
                UUID.randomUUID().toString().replace("-", ""));
        //App支付
        order.setTransactionType(WxTransactionType.APP);
        data.put("orderInfo", appService.orderInfo(order));
        return data;
    }

    /**
     * 获取二维码图像
     * 二维码支付
     *
     * @return 二维码图像
     */
    @RequestMapping(value = "toQrPay.jpg", produces = "image/jpeg;charset=UTF-8")
    public byte[] toWxQrPay() throws IOException {
        //获取对应的支付账户操作工具（可根据账户id）
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(service.genQrPay(new top.italks.demo.pay.common.bean.PayOrder("订单title", "摘要", new BigDecimal(0.01), System.currentTimeMillis() + "", WxTransactionType.NATIVE)), "JPEG", baos);
        return baos.toByteArray();
    }


    /**
     * 刷卡付,pos主动扫码付款(条码付)
     *
     * @param authCode 授权码，条码等
     * @param price    金额
     * @return 支付结果
     */
    @RequestMapping(value = "microPay")
    public Map<String, Object> microPay(BigDecimal price, String authCode) throws IOException {
        //获取对应的支付账户操作工具（可根据账户id）
        //条码付
        top.italks.demo.pay.common.bean.PayOrder order = new top.italks.demo.pay.common.bean.PayOrder("huodull order", "huodull order",
                null == price ? new BigDecimal(0.01) : price,
                UUID.randomUUID().toString().replace("-", ""),
                WxTransactionType.MICROPAY);
        //设置授权码，条码等
        order.setAuthCode(authCode);
        //支付结果
        Map<String, Object> params = service.microPay(order);
        //校验
        if (service.verify(params)) {

            //支付校验通过后的处理
            //......业务逻辑处理块........

        }
        //这里开发者自行处理
        return params;
    }

    /**
     * 支付回调地址
     *
     * @param request
     * @return
     */
    @RequestMapping(value = "payBack.json")
    public String payBack(HttpServletRequest request) throws IOException {

        //获取支付方返回的对应参数
        Map<String, Object> params = service.getParameter2Map(request.getParameterMap(), request.getInputStream());
        if (null == params) {
            return service.getPayOutMessage("fail", "失败").toMessage();
        }

        //校验
        if (service.verify(params)) {
            //这里处理业务逻辑
            //......业务逻辑处理块........
            return service.getPayOutMessage("success", "成功").toMessage();
        }

        return service.getPayOutMessage("fail", "失败").toMessage();
    }

    /**
     * 查询
     *
     * @param order 订单的请求体
     * @return 返回查询回来的结果集，支付方原值返回
     */
    @RequestMapping("query")
    public Map<String, Object> query(QueryOrder order) {
        return service.query(order.getTradeNo(), order.getOutTradeNo());
    }

    /**
     * 交易关闭接口
     *
     * @param order 订单的请求体
     * @return 返回支付方交易关闭后的结果
     */
    @RequestMapping("close")
    public Map<String, Object> close(QueryOrder order) {
        return service.close(order.getTradeNo(), order.getOutTradeNo());
    }


    /**
     * 查询退款
     *
     * @param order 订单的请求体
     * @return 返回支付方查询退款后的结果
     */
    @RequestMapping("refundquery")
    public Map<String, Object> refundquery(QueryOrder order) {
        return service.refundquery(order.getTradeNo(), order.getOutTradeNo());
    }

    /**
     * 下载对账单
     *
     * @param order 订单的请求体
     * @return 返回支付方下载对账单的结果
     */
    @RequestMapping("downloadbill")
    public Object downloadbill(QueryOrder order) {
        return service.downloadbill(order.getBillDate(), order.getBillType());
    }


    /**
     * 通用查询接口，根据 WxTransactionType 类型进行实现,此接口不包括退款
     *
     * @param order 订单的请求体
     * @return 返回支付方对应接口的结果
     */
    @RequestMapping("secondaryInterface")
    public Map<String, Object> secondaryInterface(QueryOrder order) {
        top.italks.demo.pay.common.bean.TransactionType type = WxTransactionType.valueOf(order.getTransactionType());
        return service.secondaryInterface(order.getTradeNoOrBillDate(), order.getOutTradeNoBillType(), type);
    }


    /**
     * 转账到余额
     *
     * @param order 转账订单
     * @return 对应的转账结果
     */
    @RequestMapping("transfer")
    public Map<String, Object> transfer(top.italks.demo.pay.common.bean.TransferOrder order) {
        order.setOutNo("partner_trade_no 商户转账订单号");
        order.setPayeeAccount("用户openid");
        order.setPayeeName("收款用户姓名， 非必填，如果填写将强制验证收款人姓名");
        order.setRemark("转账备注, 非必填");
        order.setAmount(new BigDecimal(10));

        //转账到余额，这里默认值是转账到银行卡
        order.setTransferType(WxTransferType.TRANSFERS);

        return service.transfer(order);
    }


    /**
     * 转账到银行卡
     *
     * @param order 转账订单
     * @return 对应的转账结果
     */
    @RequestMapping("transferPayBank")
    public Map<String, Object> transferPayBank(top.italks.demo.pay.common.bean.TransferOrder order) {
        order.setOutNo("partner_trade_no 商户转账订单号");
        //采用标准RSA算法，公钥由微信侧提供,将公钥信息配置在PayConfigStorage#setKeyPublic(String)
        order.setPayeeAccount("enc_bank_no 收款方银行卡号");
        order.setPayeeName("收款方用户名");
        order.setBank(WxBank.ABC);
        order.setRemark("转账备注, 非必填");
        order.setAmount(new BigDecimal(10));
        //转账到银行卡，这里默认值是转账到银行卡
        order.setTransferType(WxTransferType.PAY_BANK);

        return service.transfer(order);
    }

    /**
     * 转账查询
     *
     * @param outNo          商户转账订单号
     * @param wxTransferType 微信转账类型，
     *                       .....这里没办法了只能这样写(┬＿┬)，请见谅
     *                       <p>
     *                       <br/>
     *                       <a href="https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3">企业付款到零钱</a>
     *                       <a href="https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_3">商户企业付款到银行卡</a>
     *                       <br/>
     * @return 对应的转账订单
     */
    @RequestMapping("transferQuery")
    public Map<String, Object> transferQuery(String outNo, String wxTransferType) {
        //默认查询银行卡的记录 top.italks.demo.pay.wx.bean.WxTransferType#QUERY_BANK
        return service.transferQuery(outNo, wxTransferType);
    }

}
